package snapex.invoice.service.impl;

import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
import static org.mybatis.dynamic.sql.SqlBuilder.isIn;

import java.sql.Timestamp;
import java.util.List;

import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import lombok.extern.slf4j.Slf4j;
import snapex.core.mapper.InvoiceCheckMapper;
import snapex.core.mapper.InvoiceDynamicSqlSupport;
import snapex.core.mapper.InvoiceImageDynamicSqlSupport;
import snapex.core.mapper.InvoiceImageMapper;
import snapex.core.mapper.InvoiceMapper;
import snapex.core.model.Invoice;
import snapex.core.model.InvoiceCheck;
import snapex.core.model.InvoiceImage;
import snapex.invoice.service.IInvoiceService;

@Slf4j
@Service
@Transactional
public class InvoiceService implements IInvoiceService {

	@Autowired
	InvoiceMapper invoiceMapper;
	
	@Autowired
	InvoiceCheckMapper invoiceCheckMapper;
	
	@Autowired
	InvoiceImageMapper invoiceImageMapper;
	
	@Override
	public Invoice getInvoice(String invoiceId) {
		
		List<Invoice> invoices = invoiceMapper.selectByExample().where(InvoiceDynamicSqlSupport.invoiceId, isEqualTo(invoiceId)).build().execute();
		
		if(!invoices.isEmpty()) {
			return invoices.get(0);
		}
		
		return null;
	}
	
	@Override
	public Invoice getInvoice(String invoiceCode, String invoiceNumber, String invoiceDate) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public InvoiceCheck getInvoiceCheck(String invoiceCode, String invoiceNumber, String invoiceDate) {
		
		List<Invoice> invoices = invoiceMapper.selectByExample()
			.where(InvoiceDynamicSqlSupport.invoiceCode, isEqualTo(invoiceCode))
			.and(InvoiceDynamicSqlSupport.invoiceNumber, isEqualTo(invoiceNumber))
			.and(InvoiceDynamicSqlSupport.invoiceDate, isEqualTo(invoiceDate))
			.build().execute();
		
		if(invoices.isEmpty()) {
			Invoice invoice = new Invoice();
			invoice.setInvoiceCode(invoiceCode);
			invoice.setInvoiceNumber(invoiceNumber);
			invoice.setInvoiceDate(invoiceDate);
			invoice.setInvoiceId(generateInvoideId());
			invoice.setCreateTimestamp(new Timestamp(System.currentTimeMillis()));
			invoiceMapper.insertSelective(invoice);
			
			return null;
		}
		
		return invoiceCheckMapper.selectByPrimaryKey(invoices.get(0).getInvoiceId());
	}

	@Override
	public Invoice saveInvoice(Invoice invoice) {
		
		invoice.setCreateTimestamp(new Timestamp(System.currentTimeMillis()));
		
		if(StringUtils.isEmpty(invoice.getInvoiceId())){			
			invoice.setInvoiceId(generateInvoideId());
			
			if(invoiceMapper.insertSelective(invoice) == 0) {
				log.warn("Failed to insert invoice:{}", invoice);
			}
		}
		else {
			if(invoiceMapper.updateByPrimaryKeySelective(invoice) == 0) {
				log.warn("Failed to update invoice:{}", invoice);
			}
		}
		return invoice;
	}
	
	@Override
	public InvoiceCheck saveInvoiceCheck(Invoice invoice, InvoiceCheck invoiceCheck) {

		invoice.setCreateTimestamp(new Timestamp(System.currentTimeMillis()));
		invoiceCheck.setCreateTimestamp(new Timestamp(System.currentTimeMillis()));
		
		invoiceMapper.updateByPrimaryKeySelective(invoice);
		
		invoiceCheckMapper.deleteByPrimaryKey(invoiceCheck.getInvoiceId());
		
		invoiceCheckMapper.insert(invoiceCheck);
		
		return invoiceCheck;
	}
	
	@Override
	public String saveInvoiceImage(String invoiceId, byte[] image, String mime) {
		
		log.debug("***saveInvoiceImage: invoiceId={}",invoiceId);
		
		InvoiceImage invoiceImage = new InvoiceImage(); 
		
		invoiceImage.setInvoiceId(invoiceId);
		invoiceImage.setImage(image);
		invoiceImage.setMime(mime);
		invoiceImage.setCreateTimestamp(new Timestamp(System.currentTimeMillis()));
		invoiceImageMapper.deleteByPrimaryKey(invoiceId);
		
		invoiceImageMapper.insert(invoiceImage);
		
		Invoice invoice = invoiceMapper.selectByPrimaryKey(invoiceId);
		if(invoice == null) {
			invoice = new Invoice();
			invoice.setInvoiceId(invoiceId);
			invoice.setCreateTimestamp(new Timestamp(System.currentTimeMillis()));
			invoiceMapper.insertSelective(invoice);
		}
		
		return invoiceId;
	}
	
	@Override
	public InvoiceImage getInvoiceImage(String invoiceId) {
		return invoiceImageMapper.selectByPrimaryKey(invoiceId);		
	}
	
	@Override
	public List<InvoiceImage> getInvoiceImages(List<String> invoiceIds){
		return invoiceImageMapper.selectByExample().where(InvoiceImageDynamicSqlSupport.invoiceId, isIn(invoiceIds)).build().execute();
	}
	
	private String generateInvoideId() {
		return RandomStringUtils.randomAlphabetic(32);
	}
}
